package ru.hh.school;

import ru.hh.school.commands.ChatRouter;
import ru.hh.school.exceptions.ChatException;
import ru.hh.school.logging.Logger;
import ru.hh.school.logging.SimpleLogger;
import ru.hh.school.logging.StaticLogger;
import ru.hh.school.logging.ThreadLogger;
import ru.hh.school.persistence.ConnectionPool;
import ru.hh.school.persistence.DataRepository;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.sql.SQLException;
import java.util.HashSet;
import java.util.Set;

import static ru.hh.school.Constants.*;

public final class ServerApp {
    private ServerApp() {
    }

    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        ServerSocket listenSocket;
        try {
            listenSocket = new ServerSocket(12345, 10);
        } catch (IOException e) {
            e.printStackTrace();
            return;
        }

        Set<Room> rooms = new HashSet<Room>();
        rooms.add(new Room(1, "regular"));
        rooms.add(new Room(2, "default"));

        String className = DB_DRIVER;
        // From derby doc: adding the newInstance() guarantees that
        // Derby will be booted on any Java Virtual Machine

        Class.forName(className).newInstance();
        String dbUrl = DB_URL;
        int maxConnectionSize = CONNECTION_POOL_CAPACITY;
        ConnectionPool connectionPool;
        try {
            connectionPool = new ConnectionPool(maxConnectionSize, dbUrl);
        } catch (SQLException e) {
            StaticLogger.logError(e);
            return;
        }
        final DataRepository dataRepository = new DataRepository(connectionPool);

        final RoomManager roomManager = new RoomManager(rooms);
        final UserManager userManager = new UserManager();

        Logger logger = new ThreadLogger(1000, new SimpleLogger());
        StaticLogger.setLogger(logger);

        final ChatRouter chatRouter = new ChatRouter(roomManager, userManager, dataRepository, logger);
        while (!Thread.interrupted()) {
            try {
                final Socket socket = listenSocket.accept();
                (new Thread() {
                    public void run() {
                        try {
                            User user = new User(socket, dataRepository, userManager, roomManager, chatRouter);
                            userManager.addUser(user);
                            user.start();
                        } catch (ChatException e) {
                            StaticLogger.getLogger().logError(e);
                        }
                    }
                }).start();
            } catch (IOException e) {
                StaticLogger.getLogger().logError(e);
            }
        }
    }
}
